/*
 * AutoPtr.h
 *
 *  Created on: 2011-5-28
 *      Author: yangentao
 */

#ifndef REF_H_
#define REF_H_

#include "../pre.h"


//reference and delete it
template<typename T>
class AutoPtr {
public:
	//no explicit
	inline AutoPtr(T* val_ = 0) {
		reset(val_);
	}
public:
	//get reference
	inline T& r() {
		return *(val.get());
	}
	//get pointer
	inline T* p() {
		return val.get();
	}
	inline void reset(T* val_) {
		val.reset(val_);
	}
	inline T* operator->() {
		return val.get();
	}
private:
	boost::shared_ptr<T> val;
};


//reference , but no delete
template<typename T>
class Ptr {
public:
	//no explicit
	inline Ptr(T* val_ = 0) {
		val = val_;
	}
public:
	//get reference
	inline T& r() {
		return *val;
	}
	//get pointer
	inline T* p() {
		return val;
	}
	inline void reset(T* val_) {
		val = val_;
	}
	inline T* operator->() {
		return val;
	}
	inline void del(){
		delete val;
		val = 0;
	}
private:
	T* val;
};









template<typename T>
class Holder: boost::noncopyable{
public:
	explicit inline Holder(T* val):pValue(val), count(0){
	}
	virtual ~Holder(){
		assert(count ==0);
		Delete();
	}

public:
	inline void AddRef(){
		++count;
	}
	inline void Release(){
		if(count >0){
			--count;
		}
		if(count == 0){
			Delete();
		}
	}
	inline unsigned int Count(){
		return count;
	}
	inline T* GetPtr(){
		return pValue;
	}
	inline void Delete(){
		delete pValue;
		pValue = 0;
	}
private:
	T* pValue;
	unsigned int count;
};




template<typename T> class WeakRef;

template<typename T>
class Ref{

public:
	//no explicit
	Ref(T* val = 0){
		Set(val);
	}

	virtual ~Ref(void){
		Release();
	}
	Ref(Ref<T>& other){
		pHolder = other.pHolder;
		pHolder->AddRef();
	}
	Ref<T>& operator=(Ref<T>& other){
		pHolder = other.pHolder;
		pHolder->AddRef();
		return *this;
	}
public:
	Ref<T>& operator=(T* val){
		Set(val);
		return *this;
	}
	T* operator ->(){
		return pHolder->GetPtr();
	}
	T& operator *(){
		return *(pHolder->GetPtr());
	}
	operator T*(){
		return pHolder->GetPtr();
	}
	operator T&(){
		return *(pHolder->GetPtr());
	}

	T* p()const {
		return pHolder->GetPtr();
	}
	T& r()const {
		return *(pHolder->GetPtr());
	}

	//删除所持对象, 不改变引用计数
	inline void DeleteObject(){
		pHolder->Delete();
	}
	inline bool isEnable(){
		return pHolder.get() && pHolder->GetPtr();
	}
	void Release(){
		if(pHolder.get()){
			pHolder->Release();
			pHolder.reset();
		}
	}
	void Set(T* val){
		Release();
		if(val != 0){
			Holder<T>* ph = new Holder<T>(val);
			ph->AddRef();
			pHolder.reset(ph);
		}else{
			pHolder.reset();
		}
	}
	inline unsigned int UseCount(){
		return pHolder.get() ? pHolder->Count() : 0;
	}
	inline bool isUnique(){
		return UseCount() == 1;
	}

	boost::shared_ptr<Holder<T> >& _GetHolder(){
		return pHolder;
	}

private:
	boost::shared_ptr<Holder<T> > pHolder;
};



template<typename T>
class WeakRef{
private:
	WeakRef(){}
public:
	virtual ~WeakRef(void){
	}
	WeakRef(WeakRef<T>& other){
		pHolder = other.pHolder;
	}
	WeakRef<T>& operator=(WeakRef<T>& other){
		pHolder = other.pHolder;
		return *this;
	}

	WeakRef(Ref<T>& other){
		pHolder = other._GetHolder();
	}
	WeakRef<T>& operator=(Ref<T>& other){
		pHolder = other._GetHolder();
		return *this;
	}
public:

	T* operator ->(){
		return pHolder->GetPtr();
	}
	T& operator *(){
		return *(pHolder->GetPtr());
	}
	operator T*(){
		return pHolder->GetPtr();
	}
	operator T&(){
		return *(pHolder->GetPtr());
	}

	T* p()const {
		return pHolder->GetPtr();
	}
	T& r()const {
		return *(pHolder->GetPtr());
	}
	inline bool isEnable(){
		return pHolder.get() && pHolder->GetPtr();
	}
private:
	boost::shared_ptr<Holder<T> > pHolder;
};


#endif /* REF_H_ */
